#! /bin/sh
. "${srcdir=.}/init.sh"; path_prepend_ . ../src

# Test checking of C++ format strings.

cat <<\EOF > f-c++-2.data
# Valid: {{ doesn't count
msgid  "abc{{def"
msgstr "xyz"
# Valid: }} doesn't count
msgid  "abc}}def"
msgstr "xyz"
# Invalid: invalid msgstr
msgid  "abc{{def"
msgstr "xyz{"
# Invalid: invalid msgstr
msgid  "abc}}def"
msgstr "xyz}"
# Valid: same arguments
msgid  "abc{}{}def"
msgstr "xyz{}{}"
# Valid: same arguments
msgid  "abc{:s}{:g}def"
msgstr "xyz{:s}{:g}"
# Valid: same arguments, with different widths
msgid  "abc{:2s}def"
msgstr "xyz{:3s}"
# Invalid: Swapped argument types
msgid  "abc{:s}{:g}def"
msgstr "xyz{:g}{:s}"
# Valid: same arguments but in numbered syntax
msgid  "abc{:s}{:g}def"
msgstr "xyz{0:s}{1:g}"
# Valid: same arguments but in unnumbered syntax
msgid  "abc{0:s}{1:g}def"
msgstr "xyz{:s}{:g}"
# Valid: permutation
msgid  "abc{:s}{:g}{:c}def"
msgstr "xyz{2:c}{1:g}{0:s}"
# Invalid: too few arguments
msgid  "abc{1:d}def{0:s}"
msgstr "xyz{0:s}"
# Invalid: too few arguments
msgid  "abc{:s}def{:d}"
msgstr "xyz{:s}"
# Invalid: too many arguments
msgid  "abc{:d}def"
msgstr "xyz{:d}vw{:c}"
# Valid: same numbered arguments, with different widths
msgid  "abc{1:5s}{0:4s}"
msgstr "xyz{1:4s}{0:5s}"
# Invalid: missing argument
msgid  "abc{1:s}def{0:d}"
msgstr "xyz{0:d}"
# Invalid: missing argument
msgid  "abc{0:s}def{1:d}"
msgstr "xyz{1:d}"
# Invalid: added argument
msgid  "abc{0:d}def"
msgstr "xyz{0:d}vw{1:c}"

# Valid: type compatibility
msgid  "abc{:b}"
msgstr "xyz{:B}"
# Valid: type compatibility
msgid  "abc{:b}"
msgstr "xyz{:d}"
# Valid: type compatibility
msgid  "abc{:b}"
msgstr "xyz{:o}"
# Valid: type compatibility
msgid  "abc{:b}"
msgstr "xyz{:x}"
# Valid: type compatibility
msgid  "abc{:b}"
msgstr "xyz{:X}"

# Valid: type compatibility
msgid  "abc{:a}"
msgstr "xyz{:A}"
# Valid: type compatibility
msgid  "abc{:a}"
msgstr "xyz{:e}"
# Valid: type compatibility
msgid  "abc{:a}"
msgstr "xyz{:E}"
# Valid: type compatibility
msgid  "abc{:a}"
msgstr "xyz{:f}"
# Valid: type compatibility
msgid  "abc{:a}"
msgstr "xyz{:F}"
# Valid: type compatibility
msgid  "abc{:a}"
msgstr "xyz{:g}"
# Valid: type compatibility
msgid  "abc{:a}"
msgstr "xyz{:G}"

# Invalid: type incompatibility
msgid  "abc{:d}"
msgstr "xyz{:e}"
# Invalid: type incompatibility
msgid  "abc{:d}"
msgstr "xyz{:c}"
# Invalid: type incompatibility
msgid  "abc{:d}"
msgstr "xyz{:s}"
# Invalid: type incompatibility
msgid  "abc{:d}"
msgstr "xyz{:p}"

# Invalid: type incompatibility
msgid  "abc{:e}"
msgstr "xyz{:d}"
# Invalid: type incompatibility
msgid  "abc{:e}"
msgstr "xyz{:c}"
# Invalid: type incompatibility
msgid  "abc{:e}"
msgstr "xyz{:s}"
# Invalid: type incompatibility
msgid  "abc{:e}"
msgstr "xyz{:p}"

# Invalid: type incompatibility
msgid  "abc{:c}"
msgstr "xyz{:d}"
# Invalid: type incompatibility
msgid  "abc{:c}"
msgstr "xyz{:e}"
# Invalid: type incompatibility
msgid  "abc{:c}"
msgstr "xyz{:s}"
# Invalid: type incompatibility
msgid  "abc{:c}"
msgstr "xyz{:p}"

# Invalid: type incompatibility
msgid  "abc{:s}"
msgstr "xyz{:d}"
# Invalid: type incompatibility
msgid  "abc{:s}"
msgstr "xyz{:e}"
# Invalid: type incompatibility
msgid  "abc{:s}"
msgstr "xyz{:c}"
# Invalid: type incompatibility
msgid  "abc{:s}"
msgstr "xyz{:p}"

# Invalid: type incompatibility
msgid  "abc{:p}"
msgstr "xyz{:d}"
# Invalid: type incompatibility
msgid  "abc{:p}"
msgstr "xyz{:e}"
# Invalid: type incompatibility
msgid  "abc{:p}"
msgstr "xyz{:c}"
# Invalid: type incompatibility
msgid  "abc{:p}"
msgstr "xyz{:s}"

# Invalid: type incompatibility for width
msgid  "abc{:g}{:{}g}"
msgstr "xyz{:{}g}{:g}"

# Valid: adding an align specification
msgid  "abc{}def"
msgstr "xyz{:^}"
# Valid: adding an align specification
msgid  "abc{:}def"
msgstr "xyz{:^}"
# Valid: adding a fill-and-align specification
msgid  "abc{}def"
msgstr "xyz{: ^}"
# Valid: adding a fill-and-align specification
msgid  "abc{:}def"
msgstr "xyz{: ^}"
# Valid: removing an align specification
msgid  "abc{:^}def"
msgstr "xyz{}"
# Valid: removing an align specification
msgid  "abc{:^}def"
msgstr "xyz{:}"
# Valid: removing a fill-and-align specification
msgid  "abc{: ^}def"
msgstr "xyz{}"
# Valid: removing a fill-and-align specification
msgid  "abc{: ^}def"
msgstr "xyz{:}"

# Invalid: adding a sign specification, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float]
msgid  "abc{}def"
msgstr "xyz{:-}"
# Invalid: adding a sign specification, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float]
msgid  "abc{:}def"
msgstr "xyz{:-}"
# Valid: adding a sign specification
msgid  "abc{:d}def"
msgstr "xyz{:-d}"
# Valid: adding a sign specification
msgid  "abc{:e}def"
msgstr "xyz{:-e}"
# Invalid: adding a sign specification, since it reduces the type from [integer, character] to [integer]
msgid  "abc{:c}def"
msgstr "xyz{:-c}"
# Valid: removing a sign specification
msgid  "abc{:-}def"
msgstr "xyz{}"
# Valid: removing a sign specification
msgid  "abc{:-}def"
msgstr "xyz{:}"
# Valid: removing a sign specification
msgid  "abc{:-d}def"
msgstr "xyz{:d}"
# Valid: removing a sign specification
msgid  "abc{:-e}def"
msgstr "xyz{:e}"
# Valid: removing a sign specification
msgid  "abc{:-c}def"
msgstr "xyz{:c}"

# Invalid: adding a '#' option, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float]
msgid  "abc{}def"
msgstr "xyz{:#}"
# Invalid: adding a '#' option, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float]
msgid  "abc{:}def"
msgstr "xyz{:#}"
# Valid: adding a '#' option
msgid  "abc{:d}def"
msgstr "xyz{:#d}"
# Valid: adding a '#' option
msgid  "abc{:e}def"
msgstr "xyz{:#e}"
# Invalid: adding a '#' option, since it reduces the type from [integer, character] to [integer]
msgid  "abc{:c}def"
msgstr "xyz{:#c}"
# Valid: removing a '#' option
msgid  "abc{:#}def"
msgstr "xyz{}"
# Valid: removing a '#' option
msgid  "abc{:#}def"
msgstr "xyz{:}"
# Valid: removing a '#' option
msgid  "abc{:#d}def"
msgstr "xyz{:d}"
# Valid: removing a '#' option
msgid  "abc{:#e}def"
msgstr "xyz{:e}"
# Valid: removing a '#' option
msgid  "abc{:#c}def"
msgstr "xyz{:c}"

# Invalid: adding a '0' option, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float]
msgid  "abc{}def"
msgstr "xyz{:0}"
# Invalid: adding a '0' option, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float]
msgid  "abc{:}def"
msgstr "xyz{:0}"
# Valid: adding a '0' option
msgid  "abc{:d}def"
msgstr "xyz{:0d}"
# Valid: adding a '0' option
msgid  "abc{:e}def"
msgstr "xyz{:0e}"
# Invalid: adding a '0' option, since it reduces the type from [integer, character] to [integer]
msgid  "abc{:c}def"
msgstr "xyz{:0c}"
# Valid: removing a '0' option
msgid  "abc{:0}def"
msgstr "xyz{}"
# Valid: removing a '0' option
msgid  "abc{:0}def"
msgstr "xyz{:}"
# Valid: removing a '0' option
msgid  "abc{:0d}def"
msgstr "xyz{:d}"
# Valid: removing a '0' option
msgid  "abc{:0e}def"
msgstr "xyz{:e}"
# Valid: removing a '0' option
msgid  "abc{:0c}def"
msgstr "xyz{:c}"

# Valid: adding a width specification
msgid  "abc{}def"
msgstr "xyz{:9}"
# Valid: adding a width specification
msgid  "abc{:}def"
msgstr "xyz{:9}"
# Valid: adding a width specification
msgid  "abc{:d}def"
msgstr "xyz{:9d}"
# Valid: adding a width specification
msgid  "abc{:e}def"
msgstr "xyz{:9e}"
# Valid: adding a width specification
msgid  "abc{:c}def"
msgstr "xyz{:9c}"
# Valid: removing a width specification
msgid  "abc{:9}def"
msgstr "xyz{}"
# Valid: removing a width specification
msgid  "abc{:9}def"
msgstr "xyz{:}"
# Valid: removing a width specification
msgid  "abc{:9d}def"
msgstr "xyz{:d}"
# Valid: removing a width specification
msgid  "abc{:9e}def"
msgstr "xyz{:e}"
# Valid: removing a width specification
msgid  "abc{:9c}def"
msgstr "xyz{:c}"

# Invalid: adding a precision specification, since it reduces the type from [integer, float, character, string, bool, pointer] to [float, string]
msgid  "abc{}def"
msgstr "xyz{:.9}"
# Invalid: adding a precision specification, since it reduces the type from [integer, float, character, string, bool, pointer] to [float, string]
msgid  "abc{:}def"
msgstr "xyz{:.9}"
# Valid: adding a precision specification
msgid  "abc{:e}def"
msgstr "xyz{:.9e}"
# Invalid: adding a precision specification
msgid  "abc{:s}def"
msgstr "xyz{:.9s}"
# Valid: removing a precision specification
msgid  "abc{:.9}def"
msgstr "xyz{}"
# Valid: removing a precision specification
msgid  "abc{:.9}def"
msgstr "xyz{:}"
# Valid: removing a precision specification
msgid  "abc{:.9d}def"
msgstr "xyz{:d}"
# Valid: removing a precision specification
msgid  "abc{:.9e}def"
msgstr "xyz{:e}"
# Valid: removing a precision specification
msgid  "abc{:.9c}def"
msgstr "xyz{:c}"

# Invalid: adding an 'L' option, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float, character, bool]
msgid  "abc{}def"
msgstr "xyz{:L}"
# Invalid: adding an 'L' option, since it reduces the type from [integer, float, character, string, bool, pointer] to [integer, float, character, bool]
msgid  "abc{:}def"
msgstr "xyz{:L}"
# Valid: adding an 'L' option
msgid  "abc{:d}def"
msgstr "xyz{:Ld}"
# Valid: adding an 'L' option
msgid  "abc{:e}def"
msgstr "xyz{:Le}"
# Valid: adding an 'L' option
msgid  "abc{:c}def"
msgstr "xyz{:Lc}"
# Invalid: adding an 'L' option
msgid  "abc{:s}def"
msgstr "xyz{:Ls}"
# Valid: removing an 'L' option
msgid  "abc{:L}def"
msgstr "xyz{}"
# Valid: removing an 'L' option
msgid  "abc{:L}def"
msgstr "xyz{:}"
# Valid: removing an 'L' option
msgid  "abc{:Ld}def"
msgstr "xyz{:d}"
# Valid: removing an 'L' option
msgid  "abc{:Le}def"
msgstr "xyz{:e}"
# Valid: removing an 'L' option
msgid  "abc{:Lc}def"
msgstr "xyz{:c}"
# Valid: removing an 'L' option
msgid  "abc{:Ls}def"
msgstr "xyz{:s}"
EOF

: ${MSGFMT=msgfmt}
n=0
while read comment; do
  if test -z "$comment"; then
    read comment
  fi
  read msgid_line
  read msgstr_line
  n=`expr $n + 1`
  cat <<EOF > f-c++-2-$n.po
#, c++-format
${msgid_line}
${msgstr_line}
EOF
  fail=
  if echo "$comment" | grep 'Valid:' > /dev/null; then
    if ${MSGFMT} --check-format -o f-c++-2-$n.mo f-c++-2-$n.po; then
      :
    else
      fail=yes
    fi
  else
    ${MSGFMT} --check-format -o f-c++-2-$n.mo f-c++-2-$n.po 2> /dev/null
    if test $? = 1; then
      :
    else
      fail=yes
    fi
  fi
  if test -n "$fail"; then
    echo "Format string checking error:" 1>&2
    cat f-c++-2-$n.po 1>&2
    Exit 1
  fi
  rm -f f-c++-2-$n.po f-c++-2-$n.mo
done < f-c++-2.data

Exit 0
